/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2010.

	This file is part of Maxsi Engine.

	Maxsi Engine is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi engine is distributed in the hope that it will be useful, but WITHOUT
	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
	FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
	for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Engine. If not, see <http://www.gnu.org/licenses/>.

	MaxsiEngine.dll
	A general purpose C++ library for the Maxsi Technology Project.

	MaxsiArray.cpp
	A flexible array class that allows Variable-Value entries natively as
	well as child arrays, does the same as Maxsi::List but with a slightly
	higher overhead and more behind-the-scenes complexity.

******************************************************************************/

#include "MaxsiEngine.h"

BeginMaxsiNamespace

Array::Array()
{
	Data	=	NULL;
}

Array::~Array()
{
	Reset();
}

Array* Array::operator[](const Index_t Index)
{
	// Protect against cases where the user called the operator on a NULL-Pointer.
	if ( this == NULL ) { return NULL; }

	// If we have no data allocated, return NULL.
	if ( Data == NULL ) { return NULL; }

	ArrayHeader*	MyHeader	=	Data;

	// If we actually are an array and not a value, return the subkey Index.
	if ( MyHeader->Index.Type & MAXSIARRAY_INDEX_SUBARRAY )
	{
		// We are dealing with a sub array!
		for ( size_t I = 1; I <= MyHeader->NumEntries; I++ )
		{
			if ( (MyHeader + I)->Index == Index ) { return (Array*)&(MyHeader + I)->Self; }
		}
	}

	// If we did not have a subkey called Index, return NULL.
	return NULL;
}

void* Array::operator=(const Array* rhs)
{
	// Protect against cases where the user called the operator on a NULL-Pointer.
	if ( this == NULL ) { return NULL; }

	// If we have no data allocated, return NULL.
	if ( Data == NULL ) { return NULL; }

	// Think of the 
	ArrayHeader*	MyHeader	=	Data;

	// If we are just a value, return our value!
	if ( !(MyHeader->Index.Type & MAXSIARRAY_INDEX_SUBARRAY) )
	{
		return MyHeader->KeyValue;
	}

	// If we did not have a subkey called Index, return NULL.
	return NULL;
}

bool Array::Reset()
{
	if ( Data )
	{
		ArrayHeader*	MyHeader	=	Data;

		// First try to figure out what we are.
		if ( MyHeader->Index.Type & MAXSIARRAY_INDEX_PARENTARRAY )
		{
			// Turns out we are a parent! Holy shit!
			for ( size_t I = 1; I <= MyHeader->NumEntries; I++ )
			{
				// Clean up the actual data pointed to.
				if ( (MyHeader + 1)->Index.Type & MAXSIARRAY_INDEX_SUBARRAY )
				{
					DeleteArray((Array*)(MyHeader + I)->KeyValue);
				}
				else
				{
					IFDEL((MyHeader + I)->KeyValue);				
				}

				// Delete the index if it is a string value.
				if ( (MyHeader + I)->Index.IsChar() && (MyHeader + I)->Index.Index )
				{
					delete[] (char*)((MyHeader + I)->Index.Index);
				}
				if ( (MyHeader + I)->Index.IsWChar() )
				{
					delete[] (wchar_t*)((MyHeader + I)->Index.Index);
				}
			}
		}
		else
		{
			// Looks like we are an ordinary value! We might still point to something,
			// though, that might need deletion. Let's check!

			if ( MyHeader->KeyValue ) { delete[] MyHeader->KeyValue; }


		}

		IFDEL(Data);
	}
	return true;
}

Array* Array::Get(const Index_t Index)
{
	return operator[](Index);
}

BYTE* Array::GetB(const Index_t Index)
{
	return (BYTE*)((void*)operator=(operator[](Index)));
}

char* Array::GetA(const Index_t Index)
{
	return (char*)((void*)operator=(operator[](Index)));
}

wchar_t* Array::GetW(const Index_t Index)
{
	return (wchar_t*)((void*)operator=(operator[](Index)));
}

bool Array::Set(Index_t Index, BYTE* Buffer, size_t BufferSize)
{
	//Array*	Child	=	[Index];

	//if ( Child )
	//{
	//	Child->Data[
	//	
	//}
	return true;
}

bool DeleteArray(Array* Input)
{
	if ( Input == NULL ) { return false; }

	delete Input;

	return true;
}

EndMaxsiNamespace

